﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024-2025 LiLong                                              **
**  This file is part of OpenVisaApplication.                                   **
**                                                                              **
**  OpenVisaApplication is free software: you can redistribute it and/or modify **
**  it under the terms of the GNU General Public License as published by        **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  OpenVisaApplication is distributed in the hope that it will be useful,      **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU General Public License for more details.                                **
**                                                                              **
**  You should have received a copy of the GNU General Public License           **
**  along with OpenVisaApplication. If not, see <https://www.gnu.org/licenses/>.**
**********************************************************************************/
#include "IOTraceModel.h"

#include <AppCore/StringEscape.h>

#include <QApplication>
#include <QClipboard>

struct IOTraceData
{
    QDateTime time;
    bool tx;
    QString address;
    QString data;
    QString rawData;
};

struct IOTraceModel::Impl
{
    std::vector<IOTraceData> datas;
    QStringList headers { u8"时间", u8"类型", u8"地址", u8"数据" };
};

IOTraceModel::IOTraceModel(QObject* parent) : QAbstractTableModel(parent), m_impl(std::make_unique<Impl>()) {}

IOTraceModel::~IOTraceModel() {}

int IOTraceModel::rowCount(const QModelIndex& parent) const { return static_cast<int>(m_impl->datas.size()); }

int IOTraceModel::columnCount(const QModelIndex& parent /* = QModelIndex() */) const { return ColumnCount; }

QVariant IOTraceModel::data(const QModelIndex& index, int role /* = Qt::DisplayRole */) const
{
    if (!index.isValid())
        return {};
    if (role == Qt::DisplayRole)
    {
        const auto& d = m_impl->datas[index.row()];
        switch (static_cast<Columns>(index.column()))
        {
        case Columns::Time:
            return d.time.toString("yyyy-MM-dd hh:mm:ss.zzz");
        case Columns::Type:
            return d.tx ? QString(u8"发送") : u8"接收";
        case Columns::Address:
            return d.address;
        case Columns::Data:
            return d.data;
        }
    }
    return {};
}

QVariant IOTraceModel::headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const
{
    if (role == Qt::DisplayRole)
    {
        return orientation == Qt::Horizontal ? QVariant { m_impl->headers[section] } : section + 1;
    }
    return {};
}

Qt::ItemFlags IOTraceModel::flags(const QModelIndex& index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; }

void IOTraceModel::clear()
{
    beginResetModel();
    m_impl->datas.clear();
    endResetModel();
}

void IOTraceModel::addData(const QDateTime& time, bool rx, const QString& address, const QString& data)
{
    auto r = rowCount();
    beginInsertRows({}, r, r);
    m_impl->datas.emplace_back(IOTraceData { time, rx, address, AppCore::StringEscape::decode(data), data });
    endInsertRows();
}

void IOTraceModel::copy(const QModelIndexList& rows)
{
    if (rows.isEmpty())
        return;
    QStringList texts;
    for (const auto& row : rows)
    {
        texts.append(m_impl->datas.at(row.row()).rawData.trimmed());
    }
    qApp->clipboard()->setText(texts.join('\n'));
}
